package org.emet.service.db;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.emet.jee.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BackupRestoreService {
	private static Logger logger = LoggerFactory.getLogger(BackupRestoreService.class);
	private String bakFileName = "mysql_bak.sql";
	private String backUpPath = "C:";

	private String username = "root";
	private String password = "root";
	private String DBHome;
	private String databasename;

	public BackupRestoreService() {
		super();
	}

	public void backup() {
		if (!isMysqlHome(getDBHome()))
			throw new BusinessException("所配置的目录不是正确的数据库主目录!");

		BufferedReader br = null;
		OutputStreamWriter writer = null;
		try {
			// 将备份文件保存在服务上
			SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd.SSS");
			String filePath = getBackUpPath() + "/" + getBakFileName() + "_" + sf.format(new Date()) + ".sql";
			File file = new File(filePath);
			if (!file.exists()) {
				File parentFile = file.getParentFile();
				if (!parentFile.exists()) {
					parentFile.mkdirs();
				}
				file.createNewFile();
				if (!file.exists())
					throw new BusinessException("发生错误! 备份路径不存在!" + file.getAbsolutePath());
			} else {
				// Back up previous file
				FileUtils.copyFile(file, new File(filePath));
			}
			final String command = getDBHome() + "/bin/mysqldump --user=" + username + " --password=" + password + " "
					+ getDatabasename();
			Process child = Runtime.getRuntime().exec(command);
			br = new BufferedReader(new InputStreamReader(child.getInputStream(), "utf8"));
			writer = new OutputStreamWriter(new FileOutputStream(filePath), "utf8");
			String inStr = null;
			while ((inStr = br.readLine()) != null) {
				writer.write(inStr + "\n");
			}
			writer.flush();
		} catch (Exception e) {
			logger.error("备份时发生错误！", e);
			throw new BusinessException("备份时发生错误！");
		} finally {

			try {
				if (br != null) {
					br.close();// 关闭br
				}
				if (writer != null) {
					writer.close();// 关闭writer
				}
			} catch (IOException e) {

			}
		}
	}

	public void restore() {
		String fPath = getBakFileName();// 备份文件路径

		if (!new File(fPath).exists())
			throw new BusinessException("备份文件不存在！请先执行备份操作！");
		OutputStreamWriter writer = null;
		OutputStream out = null;
		BufferedReader br = null;
		try {
			final String command = getDBHome() + "/bin/mysql -u" + username + " -p" + password + " "
					+ getDatabasename();
			Process child = Runtime.getRuntime().exec(command);
			out = child.getOutputStream();// 控制台的输入信息作为输出流

			br = new BufferedReader(new InputStreamReader(new FileInputStream(fPath), "utf8"));
			writer = new OutputStreamWriter(out, "utf8");
			String inStr;
			while ((inStr = br.readLine()) != null) {
				writer.write(inStr + "\r\n");
			}
			writer.flush();// 关闭writer
		} catch (Exception e) {
			logger.error("还原时发生错误！", e);
			throw new BusinessException("还原时发生错误！");
		} finally {
			// 注：这里如果用缓冲方式写入文件的话，会导致中文乱码，用flush()方法则可以避免
			try {
				if (out != null) {
					out.close();// 关闭out
				}
				if (br != null) {
					br.close();// 关闭br
				}
				if (writer != null) {
					writer.close();// 关闭writer
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private boolean isMysqlHome(String homeDir) {
		File file = new File(homeDir);
		if (!file.exists())
			throw new BusinessException("数据库主目录不存在!");
		List<String> asList = Arrays.asList(file.list());
		if (!asList.contains("bin") && !asList.contains("bin/mysqld.exe"))
			return false;
		return true;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getBakFileName() {
		return bakFileName;
	}

	public void setBakFileName(String bakFileName) {
		this.bakFileName = bakFileName;
	}

	public String getPassword() {
		return password;
	}

	public String getDBHome() {
		return DBHome;
	}

	public void setDBHome(String dBHome) {
		DBHome = dBHome;
	}

	public String getDatabasename() {
		return databasename;
	}

	public void setDatabasename(String databasename) {
		this.databasename = databasename;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getBackUpPath() {
		return backUpPath;
	}

	public void setBackUpPath(String backUpPath) {
		this.backUpPath = backUpPath;
	}

}